/**
 *  TextMash - simple IDE for Clojure
 *  
 *  Copyright (C) 2010 Aleksander Naszko
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *  
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package pl.olek.textmash.workspace;

import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.TreeMap;

/**
 * 
 * @author anaszko
 *
 */
public class Settings implements Serializable {

	transient private static final TreeMap<String, Settings> settings = new TreeMap<String, Settings>();

	private static final long serialVersionUID = 1L;
	final public static String MATCH_BRACKETS = "match.brackets";
	final public static String LINE_NUMBERS = "line.numbers";
	final public static String WRAP_LINES = "wrap.lines";
	final public static String WINDOW_WIDTH = "window.width";
	final public static String WINDOW_HEIGHT = "window.height";
	final public static String WINDOW_X = "window.x";
	final public static String WINDOW_Y = "window.y";
	final public static String ENCODING = "encoding";
	final public static String VERTICAL_SELECTION = "vertical.selection";
	final public static String LINE_ENDING = "line.ending";	
	final public static String COMMENT = "comment";	
	final public static String QUICK_LOOKUP = "quick.lookup";	
	private TreeMap<String, Object> values;

	private Settings() {
		values = new TreeMap<String, Object>();
	}

	private Settings(Settings work) {
		values = new TreeMap<String, Object>(work.values);
	}

	public boolean has(String... args) {
		for (String arg : args) {
			if (!values.containsKey(arg)) {
				return false;
			}
		}
		return true;
	}

	public boolean toggle(String name) {
		Boolean old = (Boolean) values.get(name);
		if ((old == null) || (old == false)) {
			values.put(name, true);
			return true;
		} else {
			values.put(name, false);
			return false;
		}
	}

	public boolean turnOn(String name) {
		values.put(name, true);
		return true;
	}

	public boolean turnOff(String name) {
		values.put(name, false);
		return false;
	}

	public boolean isOff(String name) {
		return !isOn(name);
	}

	public boolean isOn(String name) {
		Boolean old = (Boolean) values.get(name);
		return (old != null && old == true);
	}

	public Number getNumber(String name) {
		Number result = (Number) values.get(name);
		if (result == null) {
			result = new Double(0.0);
			values.put(name, result);
		}
		return result;
	}

	public void setNumber(String name, Number number) {
		if (number instanceof Double) {
			values.put(name, number);
		} else {
			values.put(name, new Double(number.toString()));
		}
	}

	public String get(String name) {
		String result = (String) values.get(name);
		if (result == null) {
			result = "";
			values.put(name, result);
		}
		return result;
	}
	public void set(String name, Boolean value) {
		values.put(name, value);
	}
	public void set(String name, String value) {
		values.put(name, value);
	}

	public static void save(ObjectOutputStream output) {
		try {
			output.writeObject(settings);
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	@SuppressWarnings("unchecked")
	public static void load(ObjectInputStream input) {
		try {
			settings.clear();
			settings.putAll((TreeMap<String, Settings>) input.readObject());
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}
	
	public static Settings initSettings(String name) {
		Settings result = new Settings();
		result.turnOff(WRAP_LINES);
		result.turnOn(LINE_NUMBERS);
		result.turnOn(QUICK_LOOKUP);
		result.turnOn(MATCH_BRACKETS);
		result.turnOff(VERTICAL_SELECTION);
		result.set(ENCODING, "UTF8");
		result.set(COMMENT, "//");
		settings.put(name, result);
		return result;
	}

	public static Settings forkSettings(String name, Settings cfg) {
		cfg = new Settings(cfg);
		settings.put(name, cfg);
		return cfg;
	}

	public static Settings getDefaultSettings() {
		return getSettings("");
	}

	public static Settings getSettings(String name) {
		Settings result = settings.get(name);
		if (result == null) {
			result = settings.get("");
			if (result != null) {
				if (name.length() > 0) {
					result = forkSettings(name, result);
				}
			} else {
				result = initSettings(name);
			}
		}
		return result;
	}
}
